﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Google.GData.Client;
using Google.YouTube;
using System.Collections.ObjectModel;
using System.Threading.Tasks;

namespace YoutubeGetterV2
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
			DataContext = this;
			WindowTitle = "Youtube Grabber V2";
		}

		#region properties


		public String WindowTitle
		{
			get { return (String)GetValue(WindowTitleProperty); }
			set { SetValue(WindowTitleProperty, value); }
		}
		public static readonly DependencyProperty WindowTitleProperty =
			DependencyProperty.Register("WindowTitle", typeof(String), typeof(MainWindow), new UIPropertyMetadata(""));

		public ObservableCollection<YoutubeNode> MenuItems
		{
			get { return (ObservableCollection<YoutubeNode>)GetValue(MenuItemsProperty); }
			set { SetValue(MenuItemsProperty, value); }
		}
		public static readonly DependencyProperty MenuItemsProperty =
		DependencyProperty.Register("MenuItems", typeof(ObservableCollection<YoutubeNode>), typeof(MainWindow), new UIPropertyMetadata());

		public ObservableCollection<Video> VideoList
		{
            get { return (ObservableCollection<Video>)GetValue(VideoListProperty); }
			set { SetValue(VideoListProperty, value); }
		}
		public static readonly DependencyProperty VideoListProperty =
            DependencyProperty.Register("VideoList", typeof(ObservableCollection<Video>), typeof(MainWindow), new UIPropertyMetadata());

        public Video SelectedVideo
        {
            get { return (Video)GetValue(SelectedVideoProperty); }
            set { SetValue(SelectedVideoProperty, value); }
        }

        public static readonly DependencyProperty SelectedVideoProperty =
            DependencyProperty.Register("SelectedVideo", typeof(Video), typeof(MainWindow), new UIPropertyMetadata());

        
		#endregion

		#region methods
		public void Connect(object sender, RoutedEventArgs e)
		{
			Login login = new Login();
			login.ShowDialog();
			Task.Factory.StartNew((new Action(PopulateTree)));
		}

		public void CanConnect(object sender, CanExecuteRoutedEventArgs e)
		{
			e.CanExecute = YoutubeTools.request == null;
		}

		public void Download(object sender, RoutedEventArgs e)
		{
			foreach (object item in lvVideos.SelectedItems)
			{
				ListBoxItem myListBoxItem = (ListBoxItem)(lvVideos.ItemContainerGenerator.ContainerFromItem(item));
				ContentPresenter myContentPresenter = FindVisualChild<ContentPresenter>(myListBoxItem);
				DataTemplate myDataTemplate = myContentPresenter.ContentTemplate;
				YoutubeControl yControl = (YoutubeControl)myDataTemplate.FindName("ytControl", myContentPresenter);
				yControl.StartDownload();
			}
		}

		public void CanDownload(object sender, CanExecuteRoutedEventArgs e)
		{
			e.CanExecute = lvVideos != null && lvVideos.SelectedItems.Count > 0;
		}

		private void PopulateTree()
		{
			List<YoutubeNode> retValue = new List<YoutubeNode>();
			try
			{
				YoutubeNode mainNode = new YoutubeNode(YoutubeTools.request.Settings.Credentials.Username);
                mainNode.NodeColor = Color.FromRgb(200, 200, 200);
				retValue.Add(mainNode);

				YoutubeNode myVideosNode = new YoutubeNode("My videos");
				mainNode.ChildNodes.Add(myVideosNode);
				YoutubeNode myFavoritesNode = new YoutubeNode("My favorites");
				mainNode.ChildNodes.Add(myFavoritesNode);
				YoutubeNode myPlaylistsNode = new YoutubeNode("My playlists");
				mainNode.ChildNodes.Add(myPlaylistsNode); ;
				YoutubeNode mySubsNode = new YoutubeNode("My subscriptions");
				mainNode.ChildNodes.Add(mySubsNode);

				Feed<Playlist> playLists = YoutubeTools.request.GetPlaylistsFeed(YoutubeTools.request.Settings.Credentials.Username);
				foreach (Playlist playList in playLists.Entries)
				{
					myPlaylistsNode.ChildNodes.Add(new YoutubeNode(playList.Title, playList));
				}

				Feed<Subscription> subscriptions = YoutubeTools.request.GetSubscriptionsFeed(YoutubeTools.request.Settings.Credentials.Username);
				foreach (Subscription subscription in subscriptions.Entries)
				{
					mySubsNode.ChildNodes.Add(new YoutubeNode(subscription.Title, subscription));
				}
			}
			catch (Exception ex)
			{
				if (ex.GetType() == typeof(InvalidCredentialsException))
				{
					retValue = new List<YoutubeNode>();
					retValue.Add(new YoutubeNode("Invalid login!"));
					MessageBox.Show("Could not login to youtube. Invalid password?");
				}
				else
				{
					throw ex;
				}
			}
			Dispatcher.Invoke(new Action(() => MenuItems = new ObservableCollection<YoutubeNode>(retValue)));
		}

		public void ItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
		{
			YoutubeNode selectedNode = (YoutubeNode)e.NewValue;
            VideoList = new ObservableCollection<Video>();
			Task.Factory.StartNew(() => LoadVideos(selectedNode));
		}


		private void LoadVideos(YoutubeNode selectedNode)
		{
			Feed<Video> videoCache = null;
			switch (selectedNode.Title)
			{
				case "My videos":
					videoCache = YoutubeTools.request.GetVideoFeed(YoutubeTools.request.Settings.Credentials.Username);
					videoCache.AutoPaging = true;
					foreach (Video video in videoCache.Entries)
					{
						if (video.Thumbnails.Count > 0) // checking thumbnails is one way of verifying if the video is actually valid
						{
                            Dispatcher.Invoke(new Action(() => VideoList.Add(video)));
						}
					}
					break;
				case "My favorites":
					videoCache = YoutubeTools.request.GetFavoriteFeed(YoutubeTools.request.Settings.Credentials.Username);
					videoCache.AutoPaging = true;
					foreach (Video video in videoCache.Entries)
					{
						if (video.Thumbnails.Count > 0)
						{
                            Dispatcher.Invoke(new Action(() => VideoList.Add(video)));
						}
					}
					break;
				default:
					return;
			}
		}

		private childItem FindVisualChild<childItem>(DependencyObject obj)
			where childItem : DependencyObject
		{
			for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
			{
				DependencyObject child = VisualTreeHelper.GetChild(obj, i);
				if (child != null && child is childItem)
					return (childItem)child;
				else
				{
					childItem childOfChild = FindVisualChild<childItem>(child);
					if (childOfChild != null)
						return childOfChild;
				}
			}
			return null;
		}
		#endregion
	}
}
